package com.example.springboot.common.utils;


import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;

public class ListUtils {
    private ListUtils() {
    }

    public static <T> List<T> nullToEmpty(List<T> list) {
        return (List) Optional.ofNullable(list).orElse(Collections.emptyList());
    }

    public static <T, R> List<R> collect(List<T> list, Function<? super T, ? extends R> mapper) {
        return (List)nullToEmpty(list).stream().map(mapper).collect(Collectors.toList());
    }

    public static <T, R> Set<R> distinctCollect(List<T> list, Function<? super T, ? extends R> mapper) {
        return (Set)nullToEmpty(list).stream().map(mapper).collect(Collectors.toSet());
    }

    public static <T, K> Map<K, List<T>> group(List<T> list, Function<? super T, ? extends K> classifier) {
        return (Map)nullToEmpty(list).stream().collect(Collectors.groupingBy(classifier));
    }

    public static <T> List<T> sort(List<T> list, Comparator<? super T> comparator) {
        return (List)nullToEmpty(list).stream().sorted(comparator).collect(Collectors.toList());
    }

    public static <T> Integer sum(List<T> list, ToIntFunction<? super T> mapper) {
        return (Integer)nullToEmpty(list).stream().collect(Collectors.summingInt(mapper));
    }

    @Nonnull
    public static <T> List<T> filter(@Nullable Collection<T> list, @Nonnull Predicate<T> predicate) {
        if (list != null && !list.isEmpty()) {
            List<T> newList = new ArrayList();
            Iterator var3 = list.iterator();

            while(var3.hasNext()) {
                T t = (T) var3.next();
                if (predicate.test(t)) {
                    newList.add(t);
                }
            }

            return newList;
        } else {
            return Collections.emptyList();
        }
    }

    @Nonnull
    public static <T, R> List<R> map(@Nullable Collection<T> list, @Nonnull Function<T, R> mapper) {
        if (list != null && !list.isEmpty()) {
            List<R> newList = new ArrayList();
            Iterator var3 = list.iterator();

            while(var3.hasNext()) {
                T t = (T) var3.next();
                newList.add(mapper.apply(t));
            }

            return newList;
        } else {
            return Collections.emptyList();
        }
    }

    @Nonnull
    public static <T, R> List<R> map(@Nullable Collection<T> source, @Nonnull List<R> target, @Nonnull Function<T, R> mapper) {
        if (source != null && !source.isEmpty()) {
            Iterator var3 = source.iterator();

            while(var3.hasNext()) {
                T t = (T) var3.next();
                target.add(mapper.apply(t));
            }

            return target;
        } else {
            return target;
        }
    }

    @Nullable
    public static <T> T findFirst(@Nullable Collection<T> list, @Nonnull Predicate<T> predicate) {
        if (list != null && !list.isEmpty()) {
            Iterator var2 = list.iterator();

            Object t;
            do {
                if (!var2.hasNext()) {
                    return null;
                }

                t = var2.next();
            } while(!predicate.test((T) t));

            return (T) t;
        } else {
            return null;
        }
    }

    @Nonnull
    public static <T, R> Set<R> distinct(@Nullable Collection<T> list, @Nonnull Function<T, R> mapper) {
        if (list != null && !list.isEmpty()) {
            Set<R> newList = new LinkedHashSet();
            Iterator var3 = list.iterator();

            while(var3.hasNext()) {
                T t = (T) var3.next();
                newList.add(mapper.apply(t));
            }

            return newList;
        } else {
            return Collections.emptySet();
        }
    }

    @Nonnull
    public static <K, V> Map<K, List<V>> groupBy(@Nullable Collection<V> list, @Nonnull Function<V, K> mapper) {
        return groupBy(new HashMap(), list, mapper);
    }

    @Nonnull
    public static <K, V> Map<K, List<V>> groupBy(@Nonnull Map<K, List<V>> map, @Nullable Collection<V> list, @Nonnull Function<V, K> mapper) {
        if (list != null && !list.isEmpty()) {
            Iterator var3 = list.iterator();

            while(var3.hasNext()) {
                V v = (V) var3.next();
                ((List)map.computeIfAbsent(mapper.apply(v), (k) -> {
                    return new ArrayList();
                })).add(v);
            }

            return map;
        } else {
            return map;
        }
    }

    @Nonnull
    public static <K, V> Map<K, V> toMap(@Nullable Collection<V> list, @Nonnull Function<V, K> mapper) {
        if (list != null && !list.isEmpty()) {
            Map<K, V> map = new HashMap();
            Iterator var3 = list.iterator();

            while(var3.hasNext()) {
                V v = (V) var3.next();
                map.put(mapper.apply(v), v);
            }

            return map;
        } else {
            return Collections.emptyMap();
        }
    }

    @Nonnull
    public static <K, V, E> Map<K, V> toMap(@Nullable Collection<E> list, @Nonnull Function<E, K> keyMapper, @Nonnull Function<E, V> valueMapper) {
        if (list != null && !list.isEmpty()) {
            Map<K, V> map = new HashMap();
            Iterator var4 = list.iterator();

            while(var4.hasNext()) {
                E e = (E) var4.next();
                map.put(keyMapper.apply(e), valueMapper.apply(e));
            }

            return map;
        } else {
            return Collections.emptyMap();
        }
    }

    @Nonnull
    public static <T> List<T> page(@Nullable List<T> store, @Nonnull Integer pageNo, @Nonnull Integer pageSize) {
        if (store == null) {
            return Collections.emptyList();
        } else {
            int size = store.size();
            int offset = (pageNo - 1) * pageSize;
            if (offset >= size) {
                return Collections.emptyList();
            } else {
                int endOffset = Math.min(offset + pageSize, size);
                return store.subList(offset, endOffset);
            }
        }
    }

    public static <T> void forEach(@Nullable List<T> list, @Nonnull Consumer<T> foreach) {
        if (list != null) {
            list.forEach(foreach);
        }
    }

    @Nonnull
    public static <T, R> String join(@Nullable List<T> list, @Nonnull Function<T, R> mapper, @Nonnull CharSequence delimiter) {
        if (list == null) {
            return "";
        } else {
            StringJoiner joiner = new StringJoiner(delimiter);
            Iterator var4 = list.iterator();

            while(var4.hasNext()) {
                T t = (T) var4.next();
                joiner.add(mapper.apply(t).toString());
            }

            return joiner.toString();
        }
    }
}
